#pragma once
/*
线程池构成
    1.管理者线程（1个子线程）
        -控制工作线程的数量，包括增加或减少工作线程。

    2.工作线程（n个子线程）
        -从任务队列中取任务，并进行处理。
        -当任务队列为空时，被条件变量阻塞。
        -使用互斥锁进行线程同步。
        -维护当前线程数量和空闲的线程数量。
        -有最小和最大线程数量的限制。

    3.任务队列（使用queue实现）
        -使用互斥锁保护队列的访问。
        -使用条件变量来通知工作线程任务队列的状态变化。

    4.控制线程池的启动和停止。  bool
*/
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <queue>
#include <mutex>
#include <map>
#include <condition_variable>
#include <functional>
#include <future>
#include <memory>
using namespace std;

class ThreadPool{

public:
    ThreadPool(int min=2, int max=thread::hardware_concurrency());
    ~ThreadPool();
    // 添加任务 -> 任务队列
    // void addTask(function<void(void)> task);

    template<typename F, typename... Args>
    //  https://www.bilibili.com/video/BV1fw4m1r7cT?spm_id_from=333.788.player.switch&vd_source=eb0cf72aba3d9feb1fb4f01a7ae0ff00&p=9
    auto addTask(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type>    //2个& : 未定引用类型
    {
        using returnType = typename result_of<F(Args...)>::type;
        auto task = make_shared<packaged_task<returnType()>>(
            bind(forward<F>(f), forward<Args>(args)...)
        );
        future<returnType> res = task->get_future();
        {
            unique_lock<mutex> lock(m_queueMutex);
            m_tasks.emplace([task]() { (*task)(); });
            
        }
        m_condition.notify_one();
        return res;
    }



private:
    void manager(void);
    void worker(void);

private:
    thread* m_manager;
    map<thread::id,thread> m_workers;
    vector<thread::id> m_ids; // 存储已经退出了任务函数的线程的ID
    atomic<int> m_minThread;
    atomic<int> m_maxThread;
    atomic<int> m_curThread;  //线程池的线程总数
    atomic<int> m_idleThread; //空闲线程
    atomic<int> m_exitThread; //要退出的线程数
    atomic<bool> m_stop;
    queue<function<void(void)>> m_tasks;
    mutex m_queueMutex;
    mutex m_idsMutex;

    condition_variable m_condition;

};


///g++ ThreadPool.cpp -o ThreadPool -lpthread